from core.utils import render_to
from django.core import serializers

from django.shortcuts import redirect

from datetime import date

from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
from django.http import Http404, HttpResponse
from django.conf import settings
from django.db.models import Q
from django.utils.datastructures import DotExpandedDict
import json

from student.models import Student, EnrollmentSheet
from core.models import ProgramModule
from core.models import Program
from core.utils import get_display
from exams.models import Professor, SubjectYear, ExamApplication, Exam, Subject, SubjectProgram, SubjectParticipant, Executor
from analysis.forms import StudentsSchoolYearSelection, TransienceParamsSelection, SubjectSuccessSelection

@login_required
@permission_required('student.can_students_school_year')
@render_to('analysis/students_school_year.htm')
def students_school_year(request):
  academic_year_bool = False
  student_year_bool = False
  study_type_bool = False
  module_bool = False
  enrollment_type_bool = False
  study_program_bool = False
  empty_bool = False
  step = 1
  students = None
  
  form = StudentsSchoolYearSelection()
  
  if request.method == 'POST':
    step = 2
    form = StudentsSchoolYearSelection(request.POST)
    if(form.is_valid()):
      academic_year = form.cleaned_data['academic_year']
      student_year = form.cleaned_data['school_year']
      study_program = form.cleaned_data['study_program']
      module = form.cleaned_data['module']
      enrollment_type = form.cleaned_data['enrollment_type']
      study_type = form.cleaned_data['study_type']
      duplicates = form.cleaned_data['duplicates']
      
      students = EnrollmentSheet.objects.all()
      print "vsi: %d" %len(students)
      
      if academic_year != '0':
        students = students.filter(academic_year = academic_year)
        academic_year_bool = True
        print "studijsko leto: %d" %len(students)
  
      if student_year != '0':
#        student_year_temp = settings.STUDENT_YEARS['school_year']
#        print "letnik: %s" %student_year_temp
        students = students.filter(student_year = student_year)
        student_year_bool = True 
        print "letnik: %d" %len(students)
      
      temp_program = None  
      if study_program != '0':
        temp_program = SubjectProgram.objects.get(pk = study_program)
        
        students = students.filter(student_program = temp_program.program, student_course_group = temp_program.course_group)
        study_program_bool = True
        print "program: %d" %len(students)
        
      
      if module != '0':
        module_bool = True
        year = ProgramModule.objects.values('year').get(name = module)
        students = students.filter(student__modules__name = module, student_year = str(year["year"]))
        print "modul: %d" %len(students)
      
      if enrollment_type != '0':
        students = students.filter(enrollment_type = enrollment_type)
        enrollment_type_bool = True
        print "vrsta vpisa: %d" %len(students)
      
      if study_type != '0':
        study_type_bool = True
        if study_type == '1':
          students = students.filter(full_time_student = True)
        elif study_type == '2':
          students = students.filter(full_time_student = False)
        print "nacin studija: %d" %len(students)  
      
      if len(students) == 0:
        empty_bool = True
      else:
        students = students.order_by('student_program','last_name','first_name', '-academic_year', '-student_year')
        
        if duplicates == False:
          temp_student = students[0]
          temp_students = []
          temp_students.append(temp_student)
          
          for i in students:
            if i.student.pk != temp_student.student.pk:
              temp_student = i
              temp_students.append(temp_student)
          
          students = temp_students
          
      for i in range(1, len(settings.STUDY_TYPES)):
        if settings.STUDY_TYPES[i][0] == study_program:
          study_program = settings.STUDY_TYPES[i][1]
          break

      ne_glede = "Ne glede"
      if academic_year == '0':
        academic_year = ne_glede
      if student_year == '0':
        student_year = ne_glede
      if study_program == '0':
        temp_program = ne_glede
      if module == '0':
        module = ne_glede
      if enrollment_type == '0':
        enrollment_type = ne_glede   

      return {
        "step":step,
        "empty": empty_bool,
        "students": students,
        "academic_year_bool": academic_year_bool,
        "student_year_bool": student_year_bool,
        "study_type_bool": study_type_bool,
        "module_bool": module_bool,
        "study_program_bool": study_program_bool,
        "enrollment_type_bool": enrollment_type_bool,
        "academic_year": academic_year,
        "student_year": student_year,
        "study_program": temp_program,
        "module": module,
        "enrollment_type": enrollment_type,
        "study_type": study_type,
        "module": module,
        "duplicates": duplicates,
        "parameters": {
           "step": step,
           "academic_year": form.cleaned_data["academic_year"],
           "school_year": form.cleaned_data["school_year"],
           "study_program": form.cleaned_data["study_program"],
           "module": form.cleaned_data["module"],
           "enrollment_type": form.cleaned_data["enrollment_type"],
           "study_type": form.cleaned_data["study_type"]
        }
      }
   
  return {
    "form":form,
    "step":step,
  }


@login_required
@permission_required('student.can_transience')
@render_to('analysis/subject_success.htm')
def subject_success(request):
  step = 1
  
  querysetSubject = Subject.objects.all().order_by('name')
  
  form = SubjectSuccessSelection()
  form.fields["subject"].queryset = querysetSubject
  
  if request.method == 'POST':
    
    form = SubjectSuccessSelection(request.POST)  
    form.fields["subject"].queryset = querysetSubject
    
    if form.is_valid():
      step = 2
      
      subject = form.cleaned_data["subject"]
      fromDate = form.cleaned_data["fromDate"]
      toDate = form.cleaned_data["toDate"]
      
      executors = Exam.objects.values('executor').filter(
        subject__subject = subject,
        date__gte = fromDate,
        date__lte = toDate
      ).distinct()
      
      print executors
      #hack
      duplicates = []
      for i in executors:
        executor = Executor.objects.get(pk = i["executor"])
        duplicates.append((executor.pk, executor.cooperates_with_str()))
      
      duplicates = sorted(duplicates, key=lambda x: x[1])
      
      tempList = []
      executors = []
      if len(duplicates) > 0:
        temp = duplicates[0][1]
        for i in duplicates:
          if temp == i[1]:
            tempList.append(i[0])
          else:
            executors.append(tempList)
            tempList = []
            tempList.append(i[0])
            
          temp = i[1]
        executors.append(tempList)
      
      list = []
      total_students = 0
      total_students_possitive = 0
      
      total_students_exam = 0
      total_students_pos_exam = 0
      total_students_practice = 0
      total_students_pos_practice = 0
      
      total_applies = 0
      total_average_grade_exam = 0
      total_average_grade_possitive_exam = 0
      total_average_grade_practice = 0
      total_average_grade_possitive_practice = 0
      oc2 = False
      oc3 = False
      empty = False
      
      for i in executors:
        tempList = []
        
        executor = Executor.objects.filter(pk__in = i)
        print executor
      
        students_all = ExamApplication.objects.filter(
          Q(exam__subject__subject = subject), 
          (Q(exam_grade__gt = 0) | 
          Q(practice_grade__gt = 0)),
          Q(exam__date__gte = fromDate),
          Q(exam__date__lte = toDate),
          Q(exam__executor__in = executor)
        )
        
        students_all_count = students_all.count()
        print "stevilo vseh %s" %students_all_count
        
        students_possitive = students_all.filter(
          Q(exam_grade__gte = settings.POSITIVE_GRADE_BOUNDARY) | 
          Q(practice_grade__gte = settings.POSITIVE_GRADE_BOUNDARY)
        )
        
        students_possitive_count = students_possitive.count()
        
        total_students = total_students + students_all_count
        total_students_possitive = total_students_possitive + students_possitive_count
        
        average_grade_exam = 0
        average_grade_practice = 0
        
        students_exam = 0
        students_pos_exam = 0
        students_practice = 0
        students_pos_practice = 0
        
        for i in students_all:
          if i.exam.subject.rating_type == 'OC3' or i.exam.subject.rating_type == 'OC1':
            oc3 = True
            average_grade_exam = average_grade_exam + i.exam_grade
            students_exam = students_exam + 1 
            
          if i.exam.subject.rating_type == 'OC2' or i.exam.subject.rating_type == 'OC1':
            if i.practice_grade > 5:
              oc2 = True
              average_grade_practice = average_grade_practice + i.practice_grade
              students_practice = students_practice + 1
        
        total_average_grade_exam = total_average_grade_exam + average_grade_exam
        total_average_grade_practice = total_average_grade_practice + average_grade_practice
        
        total_students_exam = total_students_exam + students_exam
        total_students_practice = total_students_practice + students_practice
        
        average_grade_possitive_exam = 0
        average_grade_possitive_practice = 0
        
        for i in students_possitive:
          if i.exam.subject.rating_type == 'OC3' or i.exam.subject.rating_type == 'OC1':
            average_grade_possitive_exam = average_grade_possitive_exam + i.exam_grade
            students_pos_exam = students_pos_exam + 1
          
          if i.exam.subject.rating_type == 'OC2' or i.exam.subject.rating_type == 'OC1':
            average_grade_possitive_practice = average_grade_possitive_practice + i.practice_grade    
            students_pos_practice = students_pos_practice + 1
          
        total_average_grade_possitive_exam = total_average_grade_possitive_exam + average_grade_possitive_exam 
        total_average_grade_possitive_practice = total_average_grade_possitive_practice + average_grade_possitive_practice 
       
        total_students_pos_exam = total_students_pos_exam + students_pos_exam
        total_students_pos_practice = total_students_pos_practice + students_pos_practice
        
        if students_pos_exam > 0: 
          average_grade_possitive_exam = float(average_grade_possitive_exam) / students_pos_exam
        else:
          average_grade_possitive_exam = 0
        
        if students_pos_practice > 0:
          average_grade_possitive_practice = float(average_grade_possitive_practice) / students_pos_practice
        else:
          average_grade_possitive_practice = 0     
        
        applies = 0
        exam = Exam.objects.filter(
          subject__subject = subject,
          date__gte = fromDate,
          date__lte = toDate,
          executor__in = executor
        )
        
        if len(exam) > 0:
          exam = exam[0]
          for i in students_all:
            applies = applies + exam.number_applies_till_date(student = i.student, till = i.exam.date)
          
          total_applies = total_applies + applies
          
        if students_all_count > 0:  
          applies = float(applies) / students_all_count  
        else:
          applies = 0 
          
        if students_exam > 0:
          average_grade_exam = float(average_grade_exam) / students_exam
        else:
          average_grade_exam = 0
        
        if students_practice > 0:
          average_grade_practice = float(average_grade_practice) / students_practice
        else:
          average_grade_practice = 0        
            
          
        tempList = []
        tempList.append(executor[0].cooperates_with_str())
        tempList.append(students_all_count)
        tempList.append(students_possitive_count)
        tempList.append('{0:.2f}'.format(applies))
        tempList.append('{0:.2f}'.format(average_grade_exam))
        tempList.append('{0:.2f}'.format(average_grade_possitive_exam))
        tempList.append('{0:.2f}'.format(average_grade_practice))
        tempList.append('{0:.2f}'.format(average_grade_possitive_practice))
        
        list.append(tempList)
      
      if total_students > 0:
        total_applies = float(total_applies) / total_students

      if total_students_exam > 0:
        total_average_grade_exam = float(total_average_grade_exam) / total_students_exam
      if total_students_practice > 0:
        total_average_grade_practice = float(total_average_grade_practice) / total_students_practice   
      if total_students_pos_exam > 0:
        total_average_grade_possitive_exam = float(total_average_grade_possitive_exam) / total_students_pos_exam  
      if total_students_pos_practice > 0: 
        total_average_grade_possitive_practice = float(total_average_grade_possitive_practice) / total_students_pos_practice 
     
      
      tempList = []
      tempList.append("SKUPAJ")
      tempList.append(total_students)
      tempList.append(total_students_possitive)
      tempList.append('{0:.2f}'.format(total_applies))
      tempList.append('{0:.2f}'.format(total_average_grade_exam))
      tempList.append('{0:.2f}'.format(total_average_grade_possitive_exam))
      tempList.append('{0:.2f}'.format(total_average_grade_practice))
      tempList.append('{0:.2f}'.format(total_average_grade_possitive_practice))
       
      list.append(tempList)
      
      if not oc2 and not oc3:
        empty = True
      
      # Make parameters for printing options
      parameters = {
        "step": step, 
        "subject": subject.pk,
        "subjectObj": subject,
        "fromDate": fromDate,
        "toDate": toDate,
        "list": list,
        "oc2": oc2,
        "oc3": oc3,
        "empty": empty
      }
    
    else:
      step = 1
      form = SubjectSuccessSelection(request.POST)
      form.fields["subject"].queryset = querysetSubject
      
      parameters = {"step": step}
    
    return {
      "step": step,
      "form":form,
      "parameters": parameters
    }    
  
  return {
    "form": form,
    "step": 1
  }
 
@login_required
@permission_required('student.can_transience')
@render_to('analysis/transience.htm') 
def transience(request):
  data = None
  form = TransienceParamsSelection()
  if request.method == 'POST':
    form = TransienceParamsSelection(request.POST)
    if form.is_valid():
      program = form.cleaned_data['student_program']
      school_year = form.cleaned_data['academic_year']
      study_type_display = get_display(settings.STUDY_OPTIONS, form.cleaned_data['study_type'])
      enrollment_type_display = get_display(settings.ENROLLMENT_TYPES, form.cleaned_data['enrollment_type'])
      student_year_display = get_display(settings.STUDENT_YEARS, form.cleaned_data['student_year'])
      
      if program:
        all = EnrollmentSheet.objects.filter(student_program = program)
      else:
        all = EnrollmentSheet.objects.all()
      
      if not form.cleaned_data['academic_year'] == '0':
        all = all.filter(academic_year = form.cleaned_data['academic_year'])
      
      if not int(form.cleaned_data['student_year']) == 0:
        all = all.filter(student_year = form.cleaned_data['student_year'])
      
      if not int(form.cleaned_data['study_type']) == 0:
        all = all.filter(full_time_student = not(int(form.cleaned_data['study_type']) > 1))
        
      if not form.cleaned_data['enrollment_type'] == "0":
        all = all.filter(enrollment_type = form.cleaned_data['enrollment_type'])
      
      #dobim vse studente, ki so vpisani v letnik in potem za njih pogledam kaj se zgodi v
      #naslednjem letu
      students = list(set([e.student.pk for e in all]))
      next_year = EnrollmentSheet.next_school_year(school_year)
      number_second_year_again = 0
      number_second_year_no_more = 0
      number_second_year_next = 0
      
      for s in students:
        try:
          sheet = EnrollmentSheet.objects.get(student = s, academic_year=next_year)
          if sheet.enrollment_type == 'V1':
            number_second_year_next += 1
          elif sheet.enrollment_type == 'V2':
            number_second_year_again += 1
        except Exception, e:
          number_second_year_no_more += 1
      
      data = {
        "number_first_year": len(all),
        "number_second_year_again": number_second_year_again,
        "number_second_year_no_more": number_second_year_no_more,
        "number_second_year_next": number_second_year_next
      }
      sum = float(data["number_second_year_again"]+data["number_second_year_no_more"]+data["number_second_year_next"])
      if sum > 0:
        data["number_second_year_again_percent"] = round(data["number_second_year_again"] / sum * 100.0, 2)
        data["number_second_year_no_more_percent"] = round(data["number_second_year_no_more"] / sum * 100.0, 2)
        data["number_second_year_next_percent"] = round(data["number_second_year_next"] / sum * 100.0, 2)
      else:
        data["number_second_year_again_percent"] = 0
        data["number_second_year_no_more_percent"] = 0
        data["number_second_year_next_percent"] = 0

      display = {
        "program": program,
        "study_type": study_type_display,
        "enrollment_type": enrollment_type_display,
        "student_year": student_year_display,
        "school_year": school_year,
        "school_year_next": EnrollmentSheet.next_school_year(school_year),
        "next_student_year": get_display(settings.STUDENT_YEARS, str(int(form.cleaned_data['student_year'])+1))
      }
      return {"params_sel":False,"data":data,"display":display, "parameters": {
        "academic_year": form.cleaned_data["academic_year"],
        "student_program": program,
        "study_type": form.cleaned_data["study_type"],
        "enrollment_type": form.cleaned_data["enrollment_type"],
        "student_year": form.cleaned_data["student_year"]
      }}
  return {"form":form,"params_sel":True,"data":data}
  